package dados;

import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import basico.Cliente;



public class RepositorioCliente extends Repositorio{
	private IndiceCliente indices;
	public static final String CODCLIENTE="codCliente";
	public static final String NOME="nome";
	public static final String DATANASCIMENTO="dataNascimento";
	public static final String SEXO="sexo";
	public static final String TELEFONE="telefones";
	public static final String FLAGVALIDO="flagValido";
	//private int cardinalidade
	public RepositorioCliente(String nome) {
		super(nome);
		Class[] tipos = {Integer.class,String.class,String.class,String.class,String.class,String.class};
		this.setTipos(tipos);
		String[] nomesCamp = {CODCLIENTE,NOME,DATANASCIMENTO,SEXO,TELEFONE,FLAGVALIDO};
		this.setNomeCampos(nomesCamp);
		int[] tam = {4,102,16,2,42,2};
		this.setTamanhosCampos(tam);
		int[] pk = {0};
		this.setPk(pk);
		int[] rq = {0,1,2,3,4};
		this.setRq(rq);
		criarSequence("pk_cliente");
		gerarIndices();
	}
	
	public void incluir(Cliente c) throws Exception{
		if (c.getDataNascimento()==null || c.getDataNascimento().length()==0){
			throw new Exception(this.ERRO_CAMPO_REQUERIDO+":"+getNomeCampos()[2]);
		} else if (c.getNome()==null || c.getNome().length()==0){
			throw new Exception(this.ERRO_CAMPO_REQUERIDO+":"+getNomeCampos()[1]);
		} else if (c.getSexo()==null || c.getSexo().length()==0){
			throw new Exception(this.ERRO_CAMPO_REQUERIDO+":"+getNomeCampos()[3]);
		} else if (c.getTelefones()==null || c.getTelefones().length()==0){
			throw new Exception(this.ERRO_CAMPO_REQUERIDO+":"+getNomeCampos()[4]);
		}
		int pk = this.proximaSequence(this.getNomeSequence());
		c.setCodCliente(pk);
		if (pkExistente(pk)<0){	
			int posicao = (int)quantidadeRegistros();
			incluir(construirRegistro(c),posicao);
			this.inserirIndice(c.getNome(), posicao);
		} else {
			throw new Exception(ERRO_PK_JA_EXISTENTE);
		}
	}
	
	public void editar(Cliente c) throws Exception{
		int posicao = pkExistente(c.getCodCliente());
		if (posicao<0){
			throw new Exception(ERRO_REGISTRO_INEXISTENTE);
		} else {
			incluir(construirRegistro(c), posicao);
			this.removerIndice(posicao);
			if (c.getFlagValido().equals(Cliente.VALIDO)){
				this.inserirIndice(c.getNome(),posicao);
			}
		}
	}
	public Collection listarTodos() {
		Collection retorno=new ArrayList();
		ArrayList posicoes = new ArrayList();
		IndiceCliente cursor = this.indices;
		if (cursor!=null){
			posicoes.add(new Integer(cursor.getPosicao()));		
			while (cursor.getProximo()!=null){
				posicoes.add(new Integer(cursor.getProximo().getPosicao()));
				cursor = cursor.getProximo();
			}
		}
		Collection dados=get(posicoes);
		for (Iterator itera=dados.iterator();itera.hasNext();){
			Collection registro =(Collection)itera.next();
			retorno.add(preencherCliente(registro));
		}
		return retorno;
	}
	private Cliente preencherCliente(Collection registro) {
		Object[] objs = registro.toArray();
		//CODCLIENTE,NOME,DATANASCIMENTO,SEXO,TELEFONE,FLAGVALIDO
		Cliente retorno=new Cliente(((Integer)objs[0]).intValue(),(String)objs[1],
				(String)objs[2],(String)objs[3],(String)objs[4],(String)objs[5]);		
		
		return retorno;
	}

	public Collection listar(Cliente c){
		ArrayList retorno= new ArrayList();
		ArrayList posicoes=null,nomeAtributos=new ArrayList(),atributos=new ArrayList(6);
		//boolean temCod=false;
		if (c.getNome()!=null && c.getNome().length()!=0){
			posicoes= new ArrayList(this.getValoresIndices(c.getNome()));
		}
		//CODCLIENTE,NOME,DATANASCIMENTO,SEXO,TELEFONE,FLAGVALIDO
		if (c.getCodCliente()>0){
			nomeAtributos.add(CODCLIENTE);
			atributos.add(new Integer(c.getCodCliente()));
			//temCod=true;
		} else {
			atributos.add(new Integer(0));
		}
		if (c.getNome()!=null && c.getNome().length()!=0){
			nomeAtributos.add(NOME);
			atributos.add(1,c.getNome());			
		} else {
			atributos.add("");
		}
		if (c.getDataNascimento()!=null && c.getDataNascimento().length()!=0){
			nomeAtributos.add(DATANASCIMENTO);
			atributos.add(2,c.getDataNascimento());
		} else {
			atributos.add("");
		}
		
		if (c.getSexo()!=null && c.getSexo().length()!=0){
			nomeAtributos.add(SEXO);
			atributos.add(3,c.getSexo());
		} else {
			atributos.add("");
		}
		if (c.getTelefones()!=null && c.getTelefones().length()!=0){
			nomeAtributos.add(TELEFONE);
			atributos.add(4,c.getTelefones());
		} else {
			atributos.add("");
		}
		if (c.getFlagValido()!=null && c.getFlagValido().length()!=0){
			nomeAtributos.add(FLAGVALIDO);
			atributos.add(5,c.getFlagValido());
		} else {
			atributos.add("");
		}
		
		for (Iterator iter = this.getAll(posicoes, nomeAtributos, atributos).iterator(); iter.hasNext();) {			
			Iterator iterCampos = ((Collection)iter.next()).iterator();			
			int cod=0;
			//if (temCod){
				cod=((Integer)iterCampos.next()).intValue();
			//} else {
				//cod=0;
				//iterCampos.next();
			//}			
			String nome=(String)iterCampos.next();
			String data=(String)iterCampos.next();
			String sexo=(String)iterCampos.next();
			String telefone=(String)iterCampos.next();
			String flag=(String)iterCampos.next();
			Cliente temp = new Cliente(cod,nome,data,sexo,telefone,flag);
			retorno.add(temp);
		}
		return retorno;
	}
	
	private ArrayList construirRegistro(Cliente c) {
		ArrayList registro = new ArrayList();
		registro.add(new Integer(c.getCodCliente()));
		registro.add(c.getNome().substring(0,this.getTamanhosCampos()[getIndicePorNome("nome")]/2));
		registro.add(c.getDataNascimento().substring(0,this.getTamanhosCampos()[getIndicePorNome("dataNascimento")]/2));
		registro.add(c.getSexo().substring(0,this.getTamanhosCampos()[getIndicePorNome("sexo")]/2));
		registro.add(c.getTelefones().substring(0,this.getTamanhosCampos()[getIndicePorNome("telefones")]/2));
		registro.add(c.getFlagValido().substring(0,this.getTamanhosCampos()[getIndicePorNome("flagValido")]/2));
		return registro;
	}
	
	public int pkExistente(int pk) {
		boolean achei = false;
		int posicao = 0;
		long quantidadeRegistros=quantidadeRegistros();
		while(posicao<quantidadeRegistros&&!achei){
			if(((Integer)this.get(posicao,this.getPk()[0])).equals(new Integer(pk))){				
				achei=true;
			} else {
				posicao++;
			}
		}	
		if (!achei){
			posicao=-1;
		}
		return posicao;
	}
	
	

	public void gerarIndices(){
		long quantidadeRegistros=quantidadeRegistros();
		RandomAccessFile stream = abrir();
		for (int i=0;i<quantidadeRegistros;i++){
			Object[] registro = get(i,stream).toArray();
			if(((String)registro[5]).equals(Cliente.VALIDO)){
				inserirIndice((String)registro[1], i);
			}
		}		
		fechar(stream);	
	}
	public void inserirIndice(String chave,int valor){
		boolean fim = false;
		IndiceCliente indiceAtual=this.indices;
		IndiceCliente novo = new IndiceCliente(valor,chave,null);
		if (this.indices==null){
			this.indices=novo;
		} else if (indiceAtual.compareTo(novo)>0){
			novo.setProximo(this.indices);
			this.indices=novo;			
		} else {
			while (!fim){
				if (indiceAtual.getProximo()==null||
						indiceAtual.getProximo().compareTo(novo)>0){
					IndiceCliente proximo = indiceAtual.getProximo();
					indiceAtual.setProximo(novo);
					novo.setProximo(proximo);
					fim=true;					
				} else {
					indiceAtual=indiceAtual.getProximo();
				}
			}
		}
	}
	public void removerIndice (int valor){
		if (this.indices!=null){
			IndiceCliente indiceAtual=this.indices;
			if (indiceAtual.getPosicao()==valor){
				this.indices=indiceAtual.getProximo();
			} else {
				boolean removi=false;
				while (!removi&&indiceAtual.getProximo()!=null){
					if (indiceAtual.getProximo().getPosicao()==valor ){	
						if (indiceAtual.getProximo().getProximo()!=null){
							indiceAtual.setProximo(indiceAtual.getProximo().getProximo());							
						} else {
							indiceAtual.setProximo(null);
						}
						removi=true;
					}
					indiceAtual=indiceAtual.getProximo();
				}
			}
		}
	}
	public Collection getValoresIndices(String chave){
		ArrayList retorno = new ArrayList();
		IndiceCliente atual= this.indices;
		while (atual!=null){
			if (atual.getNome().compareTo(chave)>0){
				atual = null;
			} else {
				if (atual.getNome().compareTo(chave)==0){
					retorno.add(new Integer(atual.getPosicao()));
				}
				atual=atual.getProximo();
			}
		}		
		return retorno;
	}

	
	
}
